import path from 'path';

import { expect } from '@jest/globals';
import fse from 'fs-extra';

import { getJson5Obj } from '../../../../src/utils/json-util.js';
import { initExecuteCommand, runHvigorAsync, setDefaultStrictMode } from '../../common/common';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../plugins/project-builder/models/constants';
import { Project } from '../../plugins/project-builder/models/project-models';
import { ICaseRecord } from '../../plugins/report-builder/report-models';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOption, TestTaskOptionBuilder } from '../../plugins/task-builder/test-task-option';
import { commonJson5Operation } from '../../plugins/common-fun';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API10,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: {
    [ModuleTemplateType.StaticLibrary]: 1,
    [ModuleTemplateType.SharedLibraryWithC]: 1,
  },
};
/**
 *  1. hvigor-config设置收集debug symbol
 *  2. 构建app
 *  3. 构建之后检查每个模块的symbol文件夹，然后工程级目录下是否存在symbol
 *  4. 每个文件夹检查该有的产物
 */
const testFun: TestCaseFun = async (project: Project, taskConfig: TestTaskOption, record: ICaseRecord) => {
  const projectRoot = project.projectRootPath();
  setDefaultStrictMode(projectRoot);

  // hvigor-config增加配置，收集debug symbol
  const hvigorConfigPath = path.resolve(projectRoot, 'hvigor', 'hvigor-config.json5');
  const hvigorConfigObj = getJson5Obj(hvigorConfigPath);
  hvigorConfigObj.properties = {
    'ohos.collect.debugSymbol': true,
  };
  fse.writeFileSync(hvigorConfigPath, JSON.stringify(hvigorConfigObj));

  // // hsp模块开启混淆
  const hspLibraryPath = project.getModule('shareNativeCLibrary').moduleRootPath();
  await commonJson5Operation(path.resolve(hspLibraryPath, 'build-profile.json5'), async (json5) => {
    json5.buildOptionSet = [
      {
        name: 'release',
        arkOptions: {
          obfuscation: {
            ruleOptions: {
              enable: true,
              files: ['./obfuscation-rules.txt'],
            },
          },
        },
        nativeLib: {
          debugSymbol: {
            strip: true,
            exclude: [],
          },
        },
      },
    ];
  });

  // 构建har包
  const assembleHarCmd = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHar',
    buildMode: 'release',
  });
  const assembleHarResult = await runHvigorAsync(projectRoot, assembleHarCmd);
  record.addStep('编译构建Har', assembleHarResult);
  expect(assembleHarResult.stdout).toContain('BUILD SUCCESSFUL');

  // 构建app
  const assembleAppCmd = initExecuteCommand({
    mode: 'project',
    product: 'default',
    tasks: 'assembleApp',
    buildMode: 'release',
  });
  const assembleAppResult = await runHvigorAsync(projectRoot, assembleAppCmd);
  record.addStep('编译构建App', assembleAppResult);
  expect(assembleAppResult.stdout).toContain('BUILD SUCCESSFUL');

  // 解析每个模块下存在symbol/release文件夹
  project.getModuleNames().forEach((moduleName) => {
    expect(fse.existsSync(path.resolve(project.getModule(moduleName).moduleRootPath(), 'build', 'default', 'outputs', 'default', 'symbol', 'release'))).toBe(
      true,
    );
  });
  // 查看library是否存在sourceMap，namecache以及.so文件夹，注意带有modulename的前缀
  const hspDebugSymbolPath = path.resolve(hspLibraryPath, 'build', 'default', 'outputs', 'default', 'symbol', 'release');
  expect(fse.existsSync(path.resolve(hspDebugSymbolPath, 'shareNativeCLibrary-sourceMaps.map'))).toBe(true);
  expect(fse.existsSync(path.resolve(hspDebugSymbolPath, 'shareNativeCLibrary-nameCache.json'))).toBe(true);
  expect(fse.existsSync(path.resolve(hspDebugSymbolPath, 'arm64-v8a'))).toBe(true);

  // 解析app下build目录产物
  const appSymbolPath = path.resolve(projectRoot, 'build', 'outputs', 'default', 'symbol', 'release');
  expect(fse.existsSync(appSymbolPath)).toBe(true);
  project.getModuleNames().forEach((moduleName) => {
    // 打包app时不触发打包har任务
    if (moduleName !== 'staticLibrary') {
      expect(fse.existsSync(path.resolve(appSymbolPath, moduleName))).toBe(true);
    }
  });
  expect(fse.existsSync(path.resolve(appSymbolPath, 'app-symbol.zip'))).toBe(true);
};

TestCaseBuilder.builder()
  .caseName('AR20241107599884')
  // eslint-disable-next-line max-len
  .description('收集debug symbol需求测试用例')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testFun)
  .load();
